home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / lconsole / functions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  20.8 KB  |  966 lines

  1. /* functions.c: things that do the work */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/functions.c,v 6.0 1991/12/18 20:27:16 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/functions.c,v 6.0 1991/12/18 20:27:16 jpo Rel $
  9.  *
  10.  * $Log: functions.c,v $
  11.  * Revision 6.0  1991/12/18  20:27:16  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16. #include "lconsole.h"
  17. #include "qmgr.h"
  18. #include "qmgr-int.h"
  19. #include <isode/cmd_srch.h>
  20. #ifdef  BSD42
  21. #include <sys/ioctl.h>
  22. #endif
  23.  
  24. #define plural(n,s)    ((n) == 1 ? "" : (s))
  25.  
  26.  
  27. extern int    chan_update ();
  28. extern int    mta_update ();
  29. extern int    msglist_update ();
  30.  
  31. extern int    f_channel ();
  32. extern int    f_mta ();
  33. extern int    f_msg ();
  34. extern int    f_show ();
  35.  
  36. static int    f_clear ();
  37. static int      f_close ();
  38. static int    f_delay ();
  39. static int    f_decrease ();
  40. static int    f_disable ();
  41. static int    f_enable ();
  42. static int    f_help ();
  43. static int    f_increase ();
  44. static int      f_open ();
  45. static int      f_quit ();
  46. static int    f_rereadqueue ();
  47. static int    f_restart ();
  48. static int    f_shutdown ();
  49. static int    f_source ();
  50. static int      f_status ();
  51.  
  52. extern char *isodeversion, *ppversion;
  53.  
  54. static struct lc_dispatch disp[] = {
  55. {    "?",         f_help,        LC_NONE, 
  56.         "give help on a specific command"},
  57. {    "channel",    f_channel,    LC_OPEN,
  58.         "display channels or information about one"},
  59. {    "clear",    f_clear,    LC_AUTH|LC_OPEN,
  60.         "clear the delay on a channel, mta or message"},
  61. {    "close",     f_close,    LC_OPEN, 
  62.         "close a connection to a queue manager"},
  63. {    "decrease",    f_decrease,    LC_AUTH|LC_OPEN,
  64.         "decrease the number of runnable channels"},
  65. {    "delay",    f_delay,    LC_AUTH|LC_OPEN,
  66.         "delay a channel, mta or message"},
  67. {    "disable",    f_disable,    LC_AUTH|LC_OPEN,
  68.         "disable a channel, mta, message, all or submission"},
  69. {    "enable",    f_enable,    LC_AUTH|LC_OPEN,
  70.         "enable a channel, mta, message, all or submission"},
  71. {    "help",     f_help,        LC_NONE,
  72.         "give help on a specific command"},
  73. {    "increase",    f_increase,    LC_AUTH|LC_OPEN,
  74.         "increase the number of runnable channels"},
  75. {    "msg",        f_msg,        LC_OPEN,
  76.         "display msgs or information about a message"},
  77. {    "mta",        f_mta,        LC_OPEN,
  78.         "display mtas or information about one mta"},
  79. {    "open",     f_open,        LC_CLOSE,
  80.         "open a connection to a queue manager" },
  81. {    "quit",     f_quit,        LC_NONE,
  82.         "terminate the connection and exit" },
  83. {    "rereadqueue",    f_rereadqueue,     LC_AUTH|LC_OPEN,
  84.         "reread the queue"},
  85. {    "restart",     f_restart,    LC_AUTH|LC_OPEN,
  86.         "restart the queue manager" },
  87. {    "show",        f_show,        LC_OPEN,
  88.         "show messages meeting certain criteria"},
  89. {    "shutdown",    f_shutdown,    LC_AUTH|LC_OPEN,
  90.         "shutdown the queue manager"},
  91. {    "source",    f_source,    LC_NONE,
  92.         "read a file of commands"},
  93. {    "status",    f_status,    LC_OPEN,
  94.         "print the status of the queue manager"},
  95. {    NULLCP,     NULLIFP,    LC_NONE,
  96.         NULLCP }
  97. };
  98.  
  99. struct lc_dispatch *getds (name)
  100. char *name;
  101. {
  102.     register int    longest, nmatches;
  103.     register char  *p, *q;
  104.     char    buffer[BUFSIZ];
  105.     register struct lc_dispatch *ds, *fs;
  106.  
  107.     longest = nmatches = 0;
  108.     for (ds = disp; p = ds -> name; ds++) {
  109.         for (q = name; *q == *p++; q++)
  110.             if (*q == NULL)
  111.                 return ds;
  112.         if (*q == NULL)
  113.             if (q - name > longest) {
  114.                 longest = q - name;
  115.                 nmatches = 1;
  116.                 fs = ds;
  117.             }
  118.             else
  119.                 if (q - name == longest)
  120.                     nmatches++;
  121.     }
  122.  
  123.  
  124.     switch (nmatches) {
  125.         case 0:
  126.         advise (NULLCP, "unknown operation \"%s\"", name);
  127.         return NULL;
  128.  
  129.         case 1:
  130.         return fs;
  131.  
  132.         default:
  133.         for (ds = disp, p = buffer; q = ds -> name; ds++)
  134.             if (strncmp (q, name, longest) == 0) {
  135.                 (void) sprintf (p, "%s \"%s\"",
  136.                         p != buffer ? "," : "", q);
  137.                 p += strlen (p);
  138.             }
  139.         advise (NULLCP, "ambiguous operation, it could be one of:%s",
  140.                         buffer);
  141.         return NULL;
  142.     }
  143. }
  144.  
  145.  
  146. static int f_open (vec)
  147. char **vec;
  148. {
  149.     char buffer[BUFSIZ];
  150.     char prompt[BUFSIZ];
  151.     BindResult *br;
  152.     fd_set wfds, rfds;
  153.  
  154.     free_chanlist ();
  155.  
  156.     if (*++vec == NULLCP) {
  157.         if (getline ("host: ", buffer) == NOTOK ||
  158.             str2vec (buffer, vec) < 1)
  159.             return OK;
  160.     }
  161.  
  162.     if (host) free (host);
  163.     host = strdup (*vec);
  164.  
  165.     if (*++vec == NULLCP && authenticate) {
  166.         if (user == NULLCP)
  167.             user = strdup ("");
  168.         (void) sprintf (prompt, "user (%s:%s): ", host, user);
  169.         if (getline (prompt, buffer) == NOTOK)
  170.             return OK;
  171.  
  172.         if (str2vec (buffer, vec) < 1) {
  173.             authenticate = 0;
  174.             if (user) free (user);
  175.             user = NULLCP;
  176.         }
  177.     }
  178.     else if (*vec && **vec) {
  179.         if (user != NULLCP)
  180.             free (user);
  181.         user = strdup(*vec);
  182.         authenticate = 1;
  183.     }
  184.  
  185.     if (authenticate && *++vec == NULLCP) {
  186.         (void) sprintf (prompt, "password (%s:%s): ",
  187.                 host, user);
  188.         passwd = getpassword (prompt);
  189.         passwd = strdup(passwd);
  190.     }
  191.  
  192.     FD_ZERO(&rfds);
  193.     FD_ZERO(&wfds);
  194.     if (verbose) {
  195.         printf ("Connecting to %s...", host);
  196.         (void) fflush(stdout);
  197.     }
  198.     switch (init_connect (host, user, passwd, authenticate == 1 ?
  199.                   type_Qmgr_BindArgument_weakAuthentication :
  200.                   type_Qmgr_BindArgument_noAuthentication,
  201.                   &console_fd, buffer, &br)) {
  202.         default:
  203.         case NOTOK:
  204.         if (verbose)
  205.             printf ("failed: %s\n", buffer);
  206.         console_fd = NOTOK;
  207.         return NOTOK;
  208.  
  209.         case CONNECTING_1:
  210.         FD_SET (console_fd, &wfds);
  211.         break;
  212.  
  213.         case CONNECTING_2:
  214.         FD_SET (console_fd, &rfds);
  215.         break;
  216.  
  217.         case DONE:
  218.         break;
  219.     }
  220.     while (1) {
  221.         fd_set ifds, ofds;
  222.         ifds = rfds;
  223.         ofds = wfds;
  224.  
  225.         if (xselect (console_fd + 1, &ifds, &ofds, NULLFD, 1) <= 0) {
  226.             (void) putchar ('.');
  227.             (void) fflush (stdout);
  228.             continue;
  229.         }
  230.         switch (retry_connect (console_fd, buffer, &br)) {
  231.             case NOTOK:
  232.             console_fd = NOTOK;
  233.             if (verbose)
  234.                 printf ("failed: %s\n", buffer);
  235.             return NOTOK;
  236.  
  237.             case CONNECTING_1:
  238.             FD_CLR (console_fd, &rfds);
  239.             FD_SET (console_fd, &wfds);
  240.             continue;
  241.  
  242.             case CONNECTING_2:
  243.             FD_CLR (console_fd, &wfds);
  244.             FD_SET (console_fd, &rfds);
  245.             continue;
  246.  
  247.             case DONE:
  248.             break;
  249.         }
  250.         break;
  251.     }
  252.     accessmode = br -> access;
  253.     if (realhost) free (realhost);
  254.     realhost = strdup (br -> info);
  255.     if (remoteversion) free (remoteversion);
  256.     remoteversion = strdup(br -> version);
  257.     free_BindResult (br);
  258.  
  259.     if (verbose)
  260.         printf ("succeeded\n");
  261.  
  262.     return OK;
  263. }
  264.  
  265. /* ARGSUSED */
  266. static int f_close (vec)
  267. char **vec;
  268. {
  269.     char errbuf[BUFSIZ];
  270.  
  271.     if (console_fd == NOTOK)
  272.         return NOTOK;
  273.  
  274.     if (release_connect(console_fd, errbuf) != DONE)
  275.         return NOTOK;
  276.  
  277.     free_chanlist ();
  278.     console_fd = NOTOK;
  279.     return OK;
  280. }
  281.  
  282.  
  283. /* ARGSUSED */
  284. static int status_update (st, id)
  285. QmgrStatus *st;
  286. {
  287.     time_t now;
  288.     time_t secs;
  289.  
  290.     (void) time (&now);
  291.     secs = now - st -> boottime;
  292.  
  293.     printf ("Status at %s", ctime (&now));
  294.     printf ("\tConnected to qmgr on %s\n",realhost);
  295.     printf ("\tversion %s\n", remoteversion);
  296.     printf ("\trunning since %s", ctime(&st->boottime));
  297.     if (accessmode == FULL_ACCESS)
  298.         printf ("\tfull access rights\n");
  299.  
  300.     printf ("\nSummary\n");
  301.     printf ("Channels: %d channel%s running (maximum of %d)\n",
  302.         st -> currChans, plural(st -> currChans,"s"),
  303.         st -> maxChans);
  304.     printf ("Messages: %s Messages, ", datasize(st -> totalMsgs,""));
  305.     printf ("%s Delivery Reports, ", datasize(st -> totalDRs, "")),
  306.     printf ("Volume %s\n", datasize(st -> totalVolume, "b"));
  307.     printf ("Load: %.2lf ops/sec %.2lf runnable chans\n",
  308.         (double)st -> opsPerSec/100.0,
  309.         (double)st -> runnableChans / 100.0);
  310.     printf ("%5s %.2lf msgs in/s %.2f msgs out/s\n", "",
  311.         (double) st -> msgsInPerSec / 100.0,
  312.         (double) st -> msgsOutPerSec / 100.0);
  313.     printf ("\n%-10s %10s %10s %10s %10s\n", "", "Total In", "Avrg In/s",
  314.         "Total Out", "Avrg Out/s");
  315.     printf ("%-10s %10s %10.2f ",
  316.         "Messages",
  317.         datasize(st->messagesIn,""),
  318.         (double)st -> messagesIn / (double)secs);
  319.     printf ("%10s %10.2lf\n",
  320.         datasize(st -> messagesOut, ""),
  321.         (double) st -> messagesOut / (double)secs);
  322.     printf ("%-10s %10s %10.2lf ",
  323.         "Addresses",
  324.         datasize(st -> addrIn,""),
  325.         (double)st -> addrIn / (double)secs);
  326.     printf ("%10s %10.2lf\n",
  327.         datasize(st -> addrOut, ""),
  328.         (double)st -> addrOut / (double)secs);
  329.     free_QmgrStatus (st);
  330.     return OK;
  331. }
  332.  
  333. /* ARGSUSED */
  334. static int f_status (vec)
  335. char **vec;
  336. {
  337.     char errbuf[BUFSIZ];
  338.     int pid;
  339.  
  340.     if (initiate_op (console_fd, operation_Qmgr_qmgrStatus,
  341.              NULLVP, &pid, status_update, errbuf) == NOTOK) {
  342.         advise (NULLCP, "status operation failed: %s", errbuf);
  343.         return NOTOK;
  344.     }
  345.  
  346.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  347.         advise (NULLCP, "result_op: %s", errbuf);
  348.         return NOTOK;
  349.     }
  350.     return OK;
  351. }
  352.  
  353. /* ARGSUSED */
  354. static int f_increase (vec)
  355. char **vec;
  356. {
  357.     char *av[2];
  358.     int pid;
  359.     char errbuf[BUFSIZ];
  360.  
  361.     av[1] = NULLCP;
  362.     av[0] = QCTRL_INCMAX;
  363.     if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  364.              av, &pid, NULLIFP, errbuf) == NOTOK) {
  365.         advise (NULLCP, "status operation failed: %s", errbuf);
  366.         return NOTOK;
  367.     }
  368.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  369.         advise (NULLCP, "result_op: %s", errbuf);
  370.         return NOTOK;
  371.     }
  372.     return OK;
  373. }
  374.  
  375. /* ARGSUSED */
  376. static int f_decrease (vec)
  377. char **vec;
  378. {
  379.     char *av[2];
  380.     int pid;
  381.     char errbuf[BUFSIZ];
  382.  
  383.     av[1] = NULLCP;
  384.     av[0] = QCTRL_DECMAX;
  385.     if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  386.              av, &pid, NULLIFP, errbuf) == NOTOK) {
  387.         advise (NULLCP, "status operation failed: %s", errbuf);
  388.         return NOTOK;
  389.     }
  390.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  391.         advise (NULLCP, "result_op: %s", errbuf);
  392.         return NOTOK;
  393.     }
  394.     return OK;
  395. }
  396.  
  397. static int f_quit (vec)
  398. char **vec;
  399. {
  400.     if (console_fd != NOTOK)
  401.         (void) f_close (vec);
  402.     return DONE;
  403. }
  404.  
  405.  
  406. void display_status (st)
  407. ProcStatus *st;
  408. {
  409.     if (st -> enabled == 0)
  410.         printf ("%*sStatus: disabled\n", indent, "");
  411.  
  412.     if (st -> lastAttempt)
  413.         printf ("%*sLast attempted delivery: %s",
  414.             indent * 2, "",
  415.             ctime(&st -> lastAttempt));
  416.  
  417.     if (st -> lastSuccess)
  418.         printf ("%*sLast successful delivery: %s",
  419.             indent * 2, "",
  420.             ctime(&st->lastSuccess));
  421.  
  422.     if (st -> cachedUntil)
  423.         printf ("%*sDelayed until %s", indent * 2, "",
  424.             ctime (&st -> cachedUntil));
  425. }
  426.  
  427.  
  428. #ifndef TIOCGWINSZ
  429. /* ARGSUSED */
  430. #endif
  431. int     ncols (fp)
  432. FILE *fp;
  433. {
  434. #ifdef  TIOCGWINSZ
  435.     int     i;
  436.     struct winsize ws;
  437.  
  438.     if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK
  439.             && (i = ws.ws_col) > 0)
  440.         return i;
  441. #endif
  442.  
  443.     return 80;
  444. }
  445.  
  446.  
  447. static int f_help (vec)
  448. char **vec;
  449. {
  450.     register int    i, j, w;
  451.     int     columns, width, lines;
  452.     register struct lc_dispatch   *ds, *es; 
  453.  
  454.     for (width = 0,es = disp; es -> name; es++) {
  455.         if ((w = strlen(es->name)) > width)
  456.             width = w;
  457.     }
  458.     
  459.     if (*++vec == NULL) {
  460.         if ((columns = ncols (stdout) /
  461.              (width = (width + 8) & ~7)) == 0)
  462.             columns = 1;
  463.         lines = ((es - disp) + columns - 1) / columns;
  464.  
  465.         printf ("Operations:\n");
  466.         for (i = 0; i < lines; i++)
  467.             for (j = 0; j < columns; j++) {
  468.                 ds = disp + j * lines + i;
  469.                 printf ("%s", ds -> name);
  470.                 if (ds + lines >= es) {
  471.                     (void) putchar ('\n');
  472.                     break;
  473.                 }
  474.                 for (w = strlen (ds -> name);
  475.                      w < width; w = (w + 8) & ~7)
  476.                     (void) putchar ('\t');
  477.             }
  478.         printf ("\nversion info:\t%s\n\t\t%s\n",
  479.             ppversion, isodeversion);
  480.  
  481.         return OK;
  482.     }
  483.  
  484.     for (; *vec; vec++)
  485.         if (strcmp (*vec, "?") == 0) {
  486.             for (ds = disp; ds -> name; ds++)
  487.                 printf ("%-*s\t- %s\n", width,
  488.                     ds -> name, ds -> help);
  489.  
  490.             break;
  491.         }
  492.         else
  493.             if (ds = getds (*vec))
  494.                 printf ("%-*s\t- %s\n",
  495.                     width, ds -> name, ds -> help);
  496.  
  497.     return OK;
  498. }
  499.  
  500. /* ARGSUSED */
  501. static int f_restart (vec)
  502. char **vec;
  503. {
  504.     char errbuf[BUFSIZ];
  505.     int pid;
  506.  
  507.     vec[0] = QCTRL_RESTART;
  508.     if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  509.              vec, &pid, NULLIFP, errbuf) == NOTOK) {
  510.         advise (NULLCP, "status operation failed: %s", errbuf);
  511.         return NOTOK;
  512.     }
  513.  
  514.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  515.         advise (NULLCP, "result_op: %s", errbuf);
  516.         return NOTOK;
  517.     }
  518.     return OK;
  519. }
  520.  
  521. static int f_shutdown (vec)
  522. char **vec;
  523. {
  524.     char errbuf[BUFSIZ];
  525.     int pid;
  526.     char *av[2];
  527.  
  528.     av[1] = NULLCP;
  529.     av[0] = QCTRL_GRACEFUL;
  530.     if (*++vec != NULLCP) {
  531.         if (strncmp(*vec, "abort", strlen(*vec)) == 0)
  532.             vec[0] = QCTRL_ABORT;
  533.     }
  534.  
  535.     if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  536.              av, &pid, NULLIFP, errbuf) == NOTOK) {
  537.         advise (NULLCP, "status operation failed: %s", errbuf);
  538.         return NOTOK;
  539.     }
  540.  
  541.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  542.         advise (NULLCP, "result_op: %s", errbuf);
  543.         return NOTOK;
  544.     }
  545.     return OK;
  546. }
  547.  
  548.  
  549. /* ARGSUSED */
  550. static int f_rereadqueue (vec)
  551. char **vec;
  552. {
  553.     char errbuf[BUFSIZ];
  554.     int pid;
  555.     char *av[2];
  556.  
  557.     av[0] = QCTRL_REREAD;
  558.     av[1] = NULLCP;
  559.     if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  560.              av, &pid, NULLIFP, errbuf) == NOTOK) {
  561.         advise (NULLCP, "status operation failed: %s", errbuf);
  562.         return NOTOK;
  563.     }
  564.  
  565.     if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  566.         advise (NULLCP, "result_op: %s", errbuf);
  567.         return NOTOK;
  568.     }
  569.     return OK;
  570. }
  571.  
  572. int tb_match (name, tbl)
  573. char    *name;
  574. CMD_TABLE *tbl;
  575. {
  576.     int longest, nmatches;
  577.     CMD_TABLE *tp, *stp;
  578.     char *q, *p;
  579.  
  580.     longest = nmatches = 0;
  581.     for (tp = tbl; p = tp -> cmd_key; tp ++) {
  582.         for (q = name; *q == *p++; q++)
  583.             if (*q == NULL)
  584.                 return tp -> cmd_value;
  585.         if (*q == NULL)
  586.             if (q - name > longest) {
  587.                 longest = q - name;
  588.                 nmatches = 1;
  589.                 stp = tp;
  590.             }
  591.             else
  592.                 if (q - name == longest)
  593.                     nmatches++;
  594.     }
  595.     if (nmatches == 0)
  596.         return TB_NONE;
  597.     if (nmatches == 1)
  598.         return stp -> cmd_value;
  599.     return TB_AMBIG;
  600. }
  601.  
  602. static CMD_TABLE de_tbl[] = {
  603. #define DE_ALL    1
  604.     "all",    DE_ALL,
  605. #define DE_SUBMISSION 2
  606.     "submission", DE_SUBMISSION,
  607. #define DE_MESSAGE 3
  608.     "message", DE_MESSAGE,
  609. #define DE_MTA    4
  610.     "mta",    DE_MTA,
  611. #define DE_CHANNEL    5
  612.     "channel", DE_CHANNEL,
  613.     NULL
  614.     };
  615.  
  616. #define OP_DISABLE     1
  617. #define OP_ENABLE      2
  618. #define OP_CLEAR    3
  619.  
  620. static int de_generic (vec, type, str, cstr)
  621. char **vec;
  622. int type;
  623. char *str, *cstr;
  624. {
  625.     int style;
  626.     char buffer[BUFSIZ], buffer2[BUFSIZ];
  627.     char *av[NVARGS];
  628.     int pid;
  629.     char errbuf[BUFSIZ], prompt[BUFSIZ];
  630.  
  631.     switch (style = tb_match (*vec, de_tbl)) {
  632.         case TB_NONE:
  633.         advise (NULLCP, "%s is not a known action", *vec);
  634.         return NOTOK;
  635.         case TB_AMBIG:
  636.         advise (NULLCP, "'%s' is an ambiguous keyword", *vec);
  637.         return NOTOK;
  638.  
  639.         case DE_ALL:
  640.         case DE_SUBMISSION:
  641.         if (type == OP_DISABLE) {
  642.             av[0] = style == DE_ALL ? QCTRL_DISALL :
  643.                 QCTRL_DISSUB;
  644.         }
  645.         else if (type == OP_ENABLE)
  646.             av[0] = style == DE_ALL ? QCTRL_ENAALL :
  647.                 QCTRL_ENASUB;
  648.         else {
  649.             advise (NULLCP, "%s is not a known action", *vec);
  650.             return NOTOK;
  651.         }
  652.         
  653.         if (initiate_op (console_fd, operation_Qmgr_qmgrControl,
  654.                  av, &pid, NULLIFP, errbuf) == NOTOK) {
  655.             advise (NULLCP, "status operation failed: %s", errbuf);
  656.             return NOTOK;
  657.         }
  658.  
  659.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  660.             advise (NULLCP, "result_op: %s", errbuf);
  661.             return NOTOK;
  662.         }
  663.         break;
  664.  
  665.         case DE_CHANNEL:
  666.         if (*++vec == NULLCP) {
  667.             (void) sprintf (prompt, "%s channel: ", str);
  668.             if (getline (prompt, buffer) == NOTOK ||
  669.                 str2vec(buffer, vec) < 1)
  670.                 return OK;
  671.         }
  672.         if ((vec[0] = fullchanname(vec[0])) == NULLCP)
  673.             return OK;
  674.         vec[1] = cstr;
  675.         vec[2] = NULLCP;
  676.  
  677.         if (initiate_op (console_fd, operation_Qmgr_channelcontrol,
  678.                  vec, &pid, chan_update, errbuf) == NOTOK) {
  679.             advise (NULLCP, "status operation failed: %s", errbuf);
  680.             return NOTOK;
  681.         }
  682.  
  683.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  684.             advise (NULLCP, "result_op: %s", errbuf);
  685.             return NOTOK;
  686.         }
  687.         break;
  688.  
  689.         case DE_MTA:
  690.         if (*++vec == NULLCP) {
  691.             (void) sprintf (prompt, "channel containing MTA: ");
  692.             if (getline (prompt, buffer) == NOTOK ||
  693.                 str2vec(buffer, vec) < 1)
  694.                 return OK;
  695.         }
  696.         if ((vec[0] = fullchanname(vec[0])) == NULLCP)
  697.             return OK;
  698.         if (vec[1] == NULLCP) {
  699.             (void) sprintf (prompt,
  700.                     "%s (on channel %s) MTA: ", str,
  701.                     vec[0]); 
  702.             if (getline (prompt, buffer2) == NOTOK ||
  703.                 str2vec(buffer2, &vec[1]) < 1)
  704.                 return OK;
  705.         }
  706.  
  707.         vec[2] = cstr;
  708.         vec[3] = NULLCP;
  709.  
  710.         if (initiate_op (console_fd, operation_Qmgr_mtacontrol,
  711.                  vec, &pid, mta_update, errbuf) == NOTOK) {
  712.             advise (NULLCP, "status operation failed: %s", errbuf);
  713.             return NOTOK;
  714.         }
  715.  
  716.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  717.             advise (NULLCP, "result_op: %s", errbuf);
  718.             return NOTOK;
  719.         }
  720.         break;
  721.  
  722.         case DE_MESSAGE:
  723.         if (*++vec == NULLCP) {
  724.             (void) sprintf (prompt, "%s message qid: ", str);
  725.             if (getline (prompt, buffer) == NOTOK ||
  726.                 str2vec(buffer, av) < 1)
  727.                 return OK;
  728.             vec[1] = NULLCP;
  729.         }
  730.         else av[0] = *vec;
  731.         av[1] = NULLCP;
  732.         av[2] = cstr;
  733.         
  734.         if (*++vec == NULLCP) {
  735.             if (getline ("list of user numbers: ", buffer2) == NOTOK ||
  736.                 str2vec (buffer2, &av[3]) < 1)
  737.                 return OK;
  738.         }
  739.         else {
  740.             int i = 3;
  741.             while(*vec)
  742.                 av[i++] = *++vec;
  743.             av[i] = NULLCP;
  744.         }
  745.  
  746.         if (initiate_op (console_fd, operation_Qmgr_msgcontrol,
  747.                  av, &pid, NULLIFP, errbuf) == NOTOK) {
  748.             advise (NULLCP, "status operation failed: %s", errbuf);
  749.             return NOTOK;
  750.         }
  751.  
  752.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  753.             advise (NULLCP, "result_op: %s", errbuf);
  754.             return NOTOK;
  755.         }
  756.         break;
  757.         
  758.     }
  759.     return OK;
  760. }
  761.  
  762. static int f_enable (vec)
  763. char **vec;
  764. {
  765.     if (*++vec == NULLCP) {
  766.         advise (NULLCP,
  767.             "enable {all | submission | message [args] | mta [args] | channel [args] }");
  768.         return NOTOK;
  769.     }
  770.     return de_generic (vec, OP_ENABLE, "enable", CTRL_ENABLE);
  771. }
  772.  
  773. static int f_disable (vec)
  774. char **vec;
  775. {
  776.  
  777.     if (*++vec == NULLCP) {
  778.         advise (NULLCP,
  779.             "disable {all | submission | message [args] | mta [args] | channel [args] }");
  780.         return NOTOK;
  781.     }
  782.  
  783.     return de_generic (vec, OP_DISABLE, "disable", CTRL_DISABLE);
  784. }
  785.  
  786. static int f_clear (vec)
  787. char **vec;
  788. {
  789.     if (*++vec == NULLCP) {
  790.         advise (NULLCP,
  791.             "clear {channel | mta | message}");
  792.         return NOTOK;
  793.     }
  794.  
  795.     return de_generic (vec, OP_CLEAR, "clear delay", CTRL_CACHECLEAR);
  796. }
  797.  
  798. static int f_delay (vec)
  799. char **vec;
  800. {
  801.     char buffer[BUFSIZ], buffer2[BUFSIZ];
  802.     char *av[NVARGS];
  803.     int pid;
  804.     char errbuf[BUFSIZ], prompt[BUFSIZ];
  805.     char *str;
  806.  
  807.     if (*++vec == NULLCP) {
  808.         advise (NULLCP, "Specify one of channel, mta or message");
  809.         return NOTOK;
  810.     }
  811.  
  812.     str = "delay";
  813.     switch (tb_match (*vec, de_tbl)) {
  814.         case TB_NONE:
  815.         advise (NULLCP, "%s is not a known action", *vec);
  816.         return NOTOK;
  817.         case TB_AMBIG:
  818.         advise (NULLCP, "'%s' is an ambiguous keyword", *vec);
  819.         return NOTOK;
  820.  
  821.         case DE_CHANNEL:
  822.         if (*++vec == NULLCP) {
  823.             (void) sprintf (prompt, "%s channel: ", str);
  824.             if (getline (prompt, buffer) == NOTOK ||
  825.                 str2vec(buffer, vec) < 1)
  826.                 return OK;
  827.         }
  828.         if ((av[0] = fullchanname(*vec)) == NULLCP)
  829.             return OK;
  830.         av[1] = CTRL_CACHEADD;
  831.         if (*++vec == NULLCP) {
  832.             (void) sprintf (prompt, "%s channel by: ", str);
  833.             if (getline (prompt, buffer2) == NOTOK ||
  834.                 str2vec(buffer, vec) < 1)
  835.                 return OK;
  836.         }
  837.         av[2] = *vec;
  838.         av[3] = NULLCP;
  839.  
  840.         if (initiate_op (console_fd, operation_Qmgr_channelcontrol,
  841.                  av, &pid, chan_update, errbuf) == NOTOK) {
  842.             advise (NULLCP, "status operation failed: %s", errbuf);
  843.             return NOTOK;
  844.         }
  845.  
  846.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  847.             advise (NULLCP, "result_op: %s", errbuf);
  848.             return NOTOK;
  849.         }
  850.         break;
  851.  
  852.         case DE_MTA:
  853.         if (*++vec == NULLCP) {
  854.             (void) sprintf (prompt, "channel containing MTA: ");
  855.             if (getline (prompt, buffer) == NOTOK ||
  856.                 str2vec(buffer, vec) < 1)
  857.                 return OK;
  858.         }
  859.         if ((av[0] = fullchanname(*vec)) == NULLCP)
  860.             return OK;
  861.  
  862.         if (*++vec == NULLCP) {
  863.             (void) sprintf (prompt,
  864.                     "%s (on channel %s) MTA: ", str,
  865.                     vec[0]); 
  866.             if (getline (prompt, buffer2) == NOTOK ||
  867.                 str2vec(buffer2, &vec[1]) < 1)
  868.                 return OK;
  869.         }
  870.         av[1] = *vec;
  871.         vec[2] = CTRL_CACHEADD;
  872.         if (*++vec == NULLCP) {
  873.             (void) sprintf (prompt, "%s channel by: ", str);
  874.             if (getline (prompt, buffer2) == NOTOK ||
  875.                 str2vec(buffer, vec) < 1)
  876.                 return OK;
  877.         }
  878.         av[3] = *vec;
  879.         av[4] = NULLCP;
  880.  
  881.         if (initiate_op (console_fd, operation_Qmgr_mtacontrol,
  882.                  vec, &pid, mta_update, errbuf) == NOTOK) {
  883.             advise (NULLCP, "status operation failed: %s", errbuf);
  884.             return NOTOK;
  885.         }
  886.  
  887.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  888.             advise (NULLCP, "result_op: %s", errbuf);
  889.             return NOTOK;
  890.         }
  891.         break;
  892.  
  893.         case DE_MESSAGE:
  894.         if (*++vec == NULLCP) {
  895.             (void) sprintf (prompt, "%s message qid: ", str);
  896.             if (getline (prompt, buffer) == NOTOK ||
  897.                 str2vec(buffer, av) < 1)
  898.                 return OK;
  899.             vec[1] = NULLCP;
  900.         }
  901.         else av[0] = *vec;
  902.         if (*++vec == NULLCP) {
  903.             (void) sprintf (prompt, "%s channel by: ", str);
  904.             if (getline (prompt, buffer2) == NOTOK ||
  905.                 str2vec(buffer, vec) < 1)
  906.                 return OK;
  907.         }
  908.         av[1] = *vec;
  909.         av[2] = CTRL_CACHEADD;
  910.         if (*++vec == NULLCP) {
  911.             if (getline ("list of user numbers: ", buffer2) == NOTOK ||
  912.                 str2vec (buffer2, &av[3]) < 1)
  913.                 return OK;
  914.         }
  915.         else {
  916.             int i = 3;
  917.             while(*vec)
  918.                 av[i++] = *++vec;
  919.             av[i] = NULLCP;
  920.         }
  921.  
  922.         if (initiate_op (console_fd, operation_Qmgr_msgcontrol,
  923.                  av, &pid, NULLIFP, errbuf) == NOTOK) {
  924.             advise (NULLCP, "status operation failed: %s", errbuf);
  925.             return NOTOK;
  926.         }
  927.  
  928.         if (result_op (console_fd, &pid, errbuf) == NOTOK) {
  929.             advise (NULLCP, "result_op: %s", errbuf);
  930.             return NOTOK;
  931.         }
  932.         break;
  933.         
  934.     }
  935.     return OK;
  936. }
  937.  
  938. static int f_source (vec)
  939. char **vec;
  940. {
  941.     int sb;
  942.     FILE    *savein;
  943.     char buffer[BUFSIZ];
  944.  
  945.     if (*++vec == NULLCP) {
  946.         if (getline ("file: ", buffer) == NOTOK ||
  947.             str2vec (buffer, vec) < 1)
  948.             return OK;
  949.     }
  950.     savein = fp_in;
  951.     if ((fp_in = fopen (vec[0], "r")) == NULL) {
  952.         fp_in = savein;
  953.         advise (vec[0], "Can't open file");
  954.         return OK;
  955.     }
  956.     sb = batch;
  957.     batch = 1;
  958.  
  959.     interactive ();
  960.  
  961.     fp_in = savein;
  962.     batch = sb;
  963.  
  964.     return OK;
  965. }
  966.